package com.gxc.aspect;

import com.gxc.utils.RestControllerResult;
import java.io.BufferedReader;
import java.lang.reflect.Method;
import java.util.Enumeration;
import java.util.stream.Collectors;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * Aspect类.
 *
 * @author 宫新程
 * @since 2019/1/14 10:27 AM
 */
@Aspect
@Component
@Slf4j
public class RestControllerAspect {

  @Pointcut("@within(org.springframework.web.bind.annotation.RestController)")
  public void restController() {
    // 被restController注解过的类.
  }

  /** 环绕通知. */
  @Around("restController()")
  public Object restControllerAround(ProceedingJoinPoint joinPoint) throws Throwable {
    long start = System.currentTimeMillis();
    /** 获取Request对象. */
    ServletRequestAttributes requestAttributes =
        (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes();
    HttpServletRequest request = requestAttributes.getRequest();

    /** 获取请求消息头. */
    Enumeration<String> headerNames = request.getHeaderNames();
    while (headerNames.hasMoreElements()) {
      String headerName = headerNames.nextElement();
      String header = request.getHeader(headerName);
      System.out.println(headerName + "：" + header);
    }
    System.out.println("=============================");

    /** 入参 content-type 为 application/json */
    if (request.getHeader(HttpHeaders.CONTENT_TYPE).contains("application/json")) {
      BufferedReader reader = request.getReader();
      String body = reader.lines().collect(Collectors.joining(System.lineSeparator()));
      System.out.println(body);
    }

    /** 获取请求参数. */
    Enumeration<String> parameterNames1 = request.getParameterNames();
    while (parameterNames1.hasMoreElements()) {
      String paramName = parameterNames1.nextElement();
      String value = request.getParameter(paramName);
      System.out.println(paramName + "：" + value);
    }
    System.out.println("=============================");
    String url = request.getRequestURL().toString();
    System.out.println("访问url：" + url);
    String ip = request.getRemoteAddr();
    System.out.println("客户端ip：" + ip);

    Signature signature = joinPoint.getSignature();
    MethodSignature methodSignature = (MethodSignature) signature;
    Method method = methodSignature.getMethod();
    // 获取属性
    String className = joinPoint.getTarget().getClass().getName();
    String methodName = method.getName();
    String[] parameterNames = methodSignature.getParameterNames();
    Object[] args = joinPoint.getArgs();

    /** 打印内容. */
    System.out.println("类名：" + className);
    System.out.println("方法名：" + methodName);
    // 打印入参的值
    Object[] params = new Object[args.length];
    for (int i = 0; i < args.length; i++) {
      Object value = args[i];
      if ((value instanceof ServletRequest
          || value instanceof ServletResponse
          || value instanceof HttpSession)) {
        params[i] = null;
      } else {
        params[i] = value;
      }
      System.out.println("参数名称：" + parameterNames[i] + "，参数值：" + params[i]);
    }

    RestControllerResult<Object> result = new RestControllerResult<>();
    try {
      /** 放行. */
      Object proceedResult = joinPoint.proceed(args);

      // 处理返回信息
      if (proceedResult instanceof RestControllerResult) {
        RestControllerResult restResult = (RestControllerResult) proceedResult;
        result.setSuccess(restResult.isSuccess());
        result.setErrorMsg(restResult.getErrorMsg());
        result.setData(restResult.getData());
      }
    } catch (Exception e) {
      log.error("错误异常，{}", e);
      result.setSuccess(false);
      result.setErrorMsg(e.getMessage());
    }

    long end = System.currentTimeMillis();
    System.out.println("执行时间：" + (end - start) + "ms");
    System.out.println("===============================");
    return result;
  }
}
